﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using __Ts.Core.Utilities;

namespace __Ts.Core.ConfigTable
{
    public static class JsonHelper
    {
        /// <summary>
        /// 删除“无用”的权限节点
        /// </summary>
        /// <param name="json"></param>
        /// <returns></returns>
        public static string Reduce(string json)
        {
            if (string.IsNullOrEmpty(json))
                return "{}";
            Regex rgx = new Regex("(,*\"\\w+\":false)|(,*\"\\w+\":\"\")|(,*\"\\w+\":\\{\\})|(,*\"\\w+\":null)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
            while (rgx.IsMatch(json))
            {
                json = rgx.Replace(json, "");
            }
            return json.Replace("{,", "{");
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="json"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public static T GetNodeValue<T>(string json, string name)
        {
            return GetNodeValue<T>(json, name, null);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="json"></param>
        /// <param name="name"></param>
        /// <param name="subName"></param>
        /// <returns></returns>
        public static T GetNodeValue<T>(string json, string name, string subName)
        {
            if (!string.IsNullOrEmpty(json))
            {
                string catchStr = "";
                if (string.IsNullOrEmpty(subName))
                {
                    catchStr = json.GetMatch("(?<=\"" + name + "\":\"*)([^\"]+)").TrimEnd(new char[] { ',', '}', '{', '"' });
                    if (!string.IsNullOrEmpty(catchStr))
                        return (T)Convert.ChangeType(catchStr, typeof(T));
                }
                else
                {
                    catchStr = json.GetMatch("(?<=\"" + name + "\":{)([^}]+)").TrimEnd(',');
                    return GetNodeValue<T>(catchStr, subName, null);
                }
            }
            return Activator.CreateInstance<T>();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="conList"></param>
        /// <returns></returns>
        public static string Combine(IList conList)
        {
            Hashtable[] hs = new Hashtable[conList.Count];
            for (int i = 0; i < conList.Count; i++)
            {
                hs[i] = StringToHashTable(conList[i].ToString());
            }
            hs[0] = UnionHashTable(hs);
            return HashTableToString(hs[0]);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="h0"></param>
        /// <param name="h1"></param>
        /// <returns></returns>
        private static Hashtable UnionHashTable(Hashtable h0, Hashtable h1)
        {
            Hashtable hs = h0.Clone() as Hashtable;
            IDictionaryEnumerator de = h0.GetEnumerator();
            while (de.MoveNext())
            {
                string name0 = (string)de.Key;
                object value0 = de.Value;
                object value1 = h1[name0];
                if (value1 == null)
                {
                    continue;
                }
                if (value1 is string)
                {
                    if (value1.ToString().ToLower() == "true")
                    {
                        hs[name0] = value1;
                    }
                    else if (IsInt(value0.ToString()) && IsInt(value1.ToString()))
                    {
                        if (Convert.ToInt32(value1) < Convert.ToInt32(value0))
                        {
                            hs[name0] = value1;
                        }
                    }
                    else if (value1.ToString().IndexOf(",") != -1)
                    {
                        hs[name0] = unique((value1.ToString() + ',' + value0.ToString()).Split(','));
                    }
                    continue;
                }
                if (value0 is Hashtable)
                {
                    UnionHashTable((Hashtable)value0, (Hashtable)value1);
                }
            }
            h0 = hs;
            de = h1.GetEnumerator();
            while (de.MoveNext())
            {
                string name1 = (string)de.Key;
                object value1 = de.Value;
                object value0 = h0[name1];
                if (value0 == null)
                {
                    h0.Add(name1, value1);
                }
            }
            return h0;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="hs"></param>
        /// <returns></returns>
        private static Hashtable UnionHashTable(Hashtable[] hs)
        {
            Hashtable h = hs[0];
            for (int i = 1; i < hs.Length; i++)
            {
                h = UnionHashTable(h, hs[i]);
            }
            return h;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private static string unique(string[] values)
        {
            List<string> list = new List<string>();
            for (int i = 0; i < values.Length; i++)
            {
                if (list.IndexOf(values[i]) == -1)
                    list.Add(values[i]);
            }
            return string.Join(",", list.ToArray());
        }

        /// <summary>
        /// 字符串转Hashtable
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static Hashtable StringToHashTable(string s)
        {
            Hashtable obj = new Hashtable();
            if (string.IsNullOrEmpty(s))
                return obj;
            char[] tagNone = new char[] { ' ', '\"' };
            char tag0 = '{';
            char tag1 = '}';
            int index0 = 0;
            int index1 = IndexOfNextMatchTag(s, tag0, tag1, index0);
            int p0 = 1;
            int p1 = 0;
            do
            {
                p1 = s.IndexOf(":", p0);
                if (p1 < 0)
                    break;
                if (s[p0] == ',') p0 = p0 + 1;
                string name = s.Substring(p0, p1 - p0);
                name = name.Trim(tagNone);
                p0 = p1 + 1;
                if (s[p0] == tag0)
                {
                    p1 = IndexOfNextMatchTag(s, tag0, tag1, p0);
                    Hashtable value = StringToHashTable(s.Substring(p0, p1 - p0 + 1));
                    obj.Add(name, value);
                    if (s[p1 + 1] == ',')
                        p1++;
                }
                else
                {
                    if (s[p0] == '"')
                    {
                        p0 = p0 + 1;
                        string ts = s.Substring(p0, s.Length - p0);
                        p1 = p0 + ts.IndexOf("\"");
                    }
                    else
                    {
                        p1 = s.IndexOfAny(new char[] { ',', tag1 }, p0 + 1);
                    }
                    string value = s.Substring(p0, p1 - p0);
                    value = value.Trim(tagNone);
                    obj.Add(name, value);
                }
                p0 = p1 + 1;
            } while (p1 >= 0);
            return obj;
        }
        /// <summary>
        /// 取得下一个匹配标记的位置
        /// </summary>
        /// <param name="s">要搜索的字符串</param>
        /// <param name="tag0">开标记</param>
        /// <param name="tag1">关闭标记</param>
        /// <param name="start">起始位置(应指向当前的开标记)</param>
        /// <returns></returns>
        private static int IndexOfNextMatchTag(string s, char tag0, char tag1, int start)
        {
            int p = start;//目标位置
            int count = 0;//内部匹配次数
            if (start < 0 || start >= s.Length)
                return -1;
            char[] tags = { tag0, tag1 };
            do
            {
                if (s[p] == tag0)
                {
                    count++;
                }
                else
                {
                    count--;
                    if (count == 0)
                        return p;
                }
                p = s.IndexOfAny(tags, p + 1);
            } while (p >= 0);
            return -1;
        }
        /// <summary>
        /// Hashtable转字符串
        /// </summary>
        /// <param name="h"></param>
        /// <returns></returns>
        private static string HashTableToString(Hashtable h)
        {
            StringBuilder sb = new StringBuilder();
            if (h == null)
                return "";
            sb.Append("{");
            IDictionaryEnumerator de = h.GetEnumerator();
            bool isFirst = true;
            while (de.MoveNext())
            {
                if (!isFirst)
                {
                    sb.Append(",");
                }
                string name = (string)de.Key;
                sb.Append("\"" + name + "\":");
                if (de.Value is Hashtable)
                {
                    sb.Append(HashTableToString((Hashtable)de.Value));
                }
                else
                {
                    string value = (string)de.Value;
                    sb.Append("\"" + value + "\"");
                }
                isFirst = false;
            }
            sb.Append("}");
            return sb.ToString();
        }
        public static bool IsInt(string str)
        {
            return Regex.IsMatch(str, @"^[0-9]*$");
        }
    }
}
